<html id="scripting-tutorial" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Introduction to Scripting</title>
</head>

<body>

<h1>Introduction to Scripting</h1>

<h2>Introduction</h2>
<p>LZX applications can include procedural code, called 
<xref linkend="language-preliminaries">"script"</xref> as well as declarative XML tags.
</p>
<p>
Within an LZX program, script can appear</p>
<ul>
   <li>between &lt;script&gt; tags</li>
   <li>between &lt;method&gt; tags</li>
   <li>between quotation marks as an assigned value for an attribute</li>
</ul>

 



<h2>The &lt;script&gt; tag</h2>

<p>The quickest way to get a script running is to put it in
<tagname>script</tagname> tags. Code in script tags is executed
immediately. <tagname>script</tagname> tags are only embeddable in the
<tagname>canvas</tagname>. </p>
<note>
 In the program below, note  the <code>debug="true"</code>
attribute, which opens up the Laszlo Debugger. In these tutorials we will use the debugger as a scratchpad to illustrate
scripting concepts.</note>

<example title="Using the debugger">
&lt;canvas width="500" height="200" debug="true"&gt;
  &lt;script&gt;
    Debug.write("Hello, World!");
  &lt;/script&gt;
&lt;/canvas&gt;
</example>

<p>We can now use our knowledge of JavaScript to build on this foundation:</p>

<example title="Incorporating JavaScript">
&lt;canvas width="500" height="200" debug="true"&gt;
  &lt;script&gt;
    // some random scripting
    //
    var someStr = "Hello, World!";
    Debug.write(someStr);
    var first = 4;
    var second = 3;
    var result = first + second;
    Debug.write(result);
   &lt;/script&gt;
&lt;/canvas&gt;
</example>
<h3>Javascript gotchas</h3>
<p>
If you've never worked with Javascript before, you may be surprised by some subtle features of the language.
For example, consider this slight expanasion of the preceding program:</p>
<example title="JavaScript subtleties">
&lt;canvas width="500" height="200" debug="true"&gt;
  &lt;script&gt;
    // some random scripting
    //
    var someStr = "Hello, World!";
    Debug.write(someStr);
    var first = 4;
    var second = 3;
    var result = first + second;
    Debug.write(result);<em>
    Debug.write(first + " plus " + second + " is " + first + second);
    var two = 2;
    if (2 == two) {
      Debug.write("2 is two");
    }</em>
  &lt;/script&gt;
&lt;/canvas&gt;
</example>

<p>Everthing there is fine, except the "<code>4 plus 3 is &#x2026;</code>" line. Four plus three should be 7, as in 
the line immediately above it, right? What happened there is that we concatanated numbers to strings 
earlier on (<code>4 + " plus " + 3</code>), and that operation converted the numbers to strings.</p>
<p>
Laszlo documentation is not intended to provide a completed reference for Javascript. Later chapters do explain some
advanced topics in scripting, but we recommend that you have a Javascript reference handy while writing LZX.
</p>
<h3>XML characters in script</h3>

<p>Let's try a simple "for" loop:</p>

<example title="XML characters cause errors" extract="false">
&lt;canvas height="80" width="500" debug="true"&gt;
  &lt;-- the following code will not compile because of the angle bracket --&gt;
  &lt;script&gt;
    for (var i = 0; i &lt; 11; i++) {
      Debug.write(i);
    }
  &lt;/script&gt;
&lt;/canvas&gt;
</example>
  
<p>Oops!</p>

<p>Because LZX is an XML-based language, there are rules as to what is legal between 
tags (in particular, <tagname>script</tagname> tags). The "<code>&lt;</code>" character in
 the <code>for</code> loop is what is causing the problem. We are not allowed "<code>&lt;</code>" or 
"<code>&gt;</code>" characters between LZX tags.</p>

<p>Fortunately there are ways around this.</p>
<note>The next two examples are not interactive, but they are correct LZX programs</note>
<example title="Encoding XML characters" extract="false">
&lt;canvas height="120"&gt;
   &lt;script&gt;
     for (var i = 0; i <em>&amp;lt;</em> 11; i++) {
       Debug.write(i);
     }
   &lt;/script&gt;
&lt;/canvas&gt;
</example>

<example   title="Using CDATA" extract="false">
&lt;canvas height="120"&gt;
   lt;script&gt;
     <em>&lt;![CDATA[</em>
     for (var i = 0; i &lt; 11; i++) {
       Debug.write(i);
     }
     <em>]]&gt;</em>
   &lt;/script&gt;
&lt;/canvas&gt;
</example>



<p>Either of the above two methods will work. Whichever you use is up to you, 
and of course the particular application. The CDATA method is perhaps a little more practical for larger blocks of code.</p>
<h2>Functions</h2>
<p>You can write functions in <tagname>script</tagname> tags.</p>

<example title="Javascript functions">
&lt;canvas height="200" width="500" debug="true"&gt;
  &lt;script&gt;
    &lt;![CDATA[
    // write a word to the debugger
    //
    <em>function writeAWord(someWord) {
      Debug.write(someWord);
    }
    
    writeAWord("HELLO!");</em>
    ]]&gt;
  &lt;/script&gt;
&lt;/canvas&gt;
</example>

<p>Functions are global to the LZX document, and they follow the same scope rules as JavaScript.</p>

<h2>Methods</h2>

<p>Methods are in some ways similar to functions. They contain blocks of code between <tagname>method</tagname> tags, and are associated with particular classes. 
In the <xref linkend="art_assets">art assets</xref> tutorial, we saw a few methods of the <classname>LzView</classname> class that pertain to resources:</p>

<ul>
  <li><method>play</method></li>
  <li><method>stop</method></li>
  <li><method>getOffset</method></li>
  <li><method>getMaxOffset</method></li>
</ul>

<p>Let's explore methods with a simple example of a window. The
<tagname>window</tagname> element is actually a view, as we saw
before. There are a few methods that apply to it. The
<classname>window</classname> class <glossterm>extends</glossterm>
<classname>LzView</classname> class. This means that windows
<glossterm>inherit</glossterm> all the attributes and methods of views.</p>

<example title="a simple method" id="scripting-5">
&lt;canvas height="200" width="500"&gt;
  &lt;window x="20" y="20" width="150"
          title="Simple Window" resizable="true"&gt;
    &lt;button text="My button" 
            onclick="this.parent.setAttribute('title', 'You clicked it');"/&gt;
  &lt;/window&gt;
&lt;/canvas&gt;
</example>

<p>Let's break this statement apart:</p>

<pre>    onclick="this.parent.setTitle('You clicked it');"</pre>

 
<p>First, there's the </p>

<pre>    onclick=</pre>

<p>Like all of the on[event] attributes,  
this one takes JavaScript that will be run in the context of the object when the event is recieved. </p>

<p>The next part:</p>

<code>    this.parent</code>

<p>Is a reference to an object. In Javascript, the scope is generally global unless you say otherwise. That means 
that any class or instance methods or variables always need to be preceeded by the keyword <code>this</code>. As 
for the 'parent' part: Let's  start by saying that the lzx viewsystem always assigns each view a variable 'parent' 
which points to that view's hierarchical parent. View hierarchies are discussed in detail in <xref linkend="views">
subsequent chapters.</xref>
</p>

<p>Now we're going to call a method. With very few exceptions, tags in an lzx file correspond to run-time objects of the view system. 
Using xml, we can configure those objects with attributes and child nodes. Using script, we can call their APIs.
 From the documentation, we know that the <tagname>window</tagname> has a <method>setTitle</method> method that will change the
 window title to whatever string you give it.
</p> 
<p>
The last thing to note is the use of single quotes inside the function call.</p>
<h3>Using Script to manipulate attributes</h3>

<p>Remember that <classname>window</classname>  extends the <classname>LzView</classname> class. That means that each window has
all the attributes of a <tagname>view</tagname>.  Here's an example of how to use script to manipulate some of those assets.</p>

<example title="Manipulating &lt;view&gt; attributes">
&lt;canvas width="500" height="200"&gt;
  &lt;window x="100" y="30" 
          title="Window 2" name="windowTwo"&gt;
    &lt;text&gt;This is the second window.&lt;/text&gt;
  &lt;/window&gt;
  &lt;window x="20" y="20" width="150"
          title="Simple Window"&gt;
    &lt;button text="My button" 
            onclick="this.parent.parent.windowTwo.setAttribute('x', 200)"/&gt;
  &lt;/window&gt;
&lt;/canvas&gt;
</example>

<p>We're just building on the previous example here. Instead of addressing the parent view of the button, we are going two up, then one down. 
<code>this.parent.parent</code> refers to the canvas, and we point to Window 2 by using its <attribute>name</attribute> (windowTwo).</p>

<p>We are also using the <method>setAttribute</method> method, which takes two arguments: the attribute to set, and what to set it to.</p>

<p>Next, let's find a way to move Window 2 over so that we can see what's behind i, without dragging it. Clicking the button
 twice doesn't help, because all that does is reset the x attribute to a constant amount (150px).</p>

<p>Instead, we need to figure out where the second window is, and then add an increment to it each time the button is clicked. 
Looking again at the API reference for the <classname>LzView</classname> class, we can see that there is a <method>getAttribute</method> method to get the <attribute>x</attribute> attribute.</p>

<p>So we could say:</p>

<example title="getting attributes">
&lt;canvas width="500" height="200"&gt;
  &lt;window x="100" y="30" 
          title="Window 2" name="windowTwo"&gt;
    &lt;text&gt;This is the second window.&lt;/text&gt;
  &lt;/window&gt;
  &lt;window x="20" y="20" width="150"
          title="Simple Window"&gt;
    &lt;button text="My button" 
            onclick="this.parent.parent.windowTwo.setAttribute('x',
            this.parent.parent.windowTwo.getAttribute('x') + 20)"/&gt;
  &lt;/window&gt;
&lt;/canvas&gt;
</example>

<p>That works, but the code is getting pretty messy. It would be more elegant to encase all the code in a block and call 
it whenever the button is clicked&#x2026;. To do what, we could write a function:</p>

<example title="Moving window by function call">
&lt;canvas width="500" height="200"&gt;
  &lt;script&gt;
    <em>// Moves the second window twenty pixels to the right
    //
    function moveWindow() {
      var increment = 20;
      var originalX = canvas.windowTwo.getAttribute('x');
      var newX = originalX + increment;
      canvas.windowTwo.setAttribute('x', newX);
    }</em>
  &lt;/script&gt;
  &lt;window x="100" y="30" 
          title="Window 2" name="windowTwo"&gt;
    &lt;text&gt;This is the second window.&lt;/text&gt;
  &lt;/window&gt;
  &lt;window x="20" y="20" width="150"
          title="Simple Window"&gt;
    &lt;button text="My button" 
              onclick="<em>moveWindow();</em>"/&gt;
  &lt;/window&gt;
&lt;/canvas&gt;
</example>

<p>Notice how we use the "<code>canvas.</code>" syntax for pointing to the second window. We have to address the view <em>absolutely</em>. 
The code is a lot easier to understand, because we can break it up over several lines, comment it and assign appropriately-named variables.</p>

<p>However, the function is pretty detached from the button. A more elegant way of achieving the same result would be to write 
a method <em>of the button</em>.</p>

<example title="From function to method">
&lt;canvas width="500" height="200"&gt;
  &lt;window x="100" y="30" 
          title="Window 2" name="windowTwo"&gt;
    &lt;text&gt;This is the second window.&lt;/text&gt;
  &lt;/window&gt;
  &lt;window x="20" y="20" width="200"
          title="Simple Window"&gt;
    &lt;button text="My button" onclick="<em>this.moveWindow()</em>"&gt;
      <em>&lt;!-- Moves the second window twenty pixels 
           to the right --&gt;
      &lt;method name="moveWindow"&gt;
        var increment = 20;
        var originalX = this.parent.parent.windowTwo.getAttribute('x');
        var newX = originalX + increment;
        this.parent.parent.windowTwo.setAttribute('x', newX);
      &lt;/method&gt;</em>
    &lt;/button&gt;
  &lt;/window&gt;
&lt;/canvas&gt;
</example>

<p>Since methods are not not global, we have to call them relatively. In the case of the button, we use <code>this.moveWindow()</code>. 

In theory we could have a second button that, when clicked, would call a method of the first button. The only difference would be the addressing. 
Before we go any further with methods, let's take a proper look at addressing:</p>


<h2>Addressing</h2>

<p>In LZX, objects can have <attribute>name</attribute>s and/or <attribute>id</attribute>s by which they can be addressed. A <attribute>name</attribute> needs to be referred to locally,
so there can be more than one view with the same name in a file (they just can't be siblings). An <attribute>id</attribute> is global, so there can't be two views with the same <attribute>id</attribute> in a LZX file.</p>

<p>Going back to the idea of having one button call the second button's method:</p>

<example title="One button calls another's method">
&lt;canvas width="500" height="200"&gt;
  &lt;window x="100" y="60" 
          title="Window 2" name="windowTwo"&gt;
    &lt;text&gt;This is the second window.&lt;/text&gt;
  &lt;/window&gt;
  &lt;window x="20" y="20" width="210"
          title="Simple Window"&gt;
    <em>&lt;simplelayout axis="x" spacing="4"/&gt;</em>
    &lt;button text="My button" <em>name="button1"</em> 
            onclick="this.moveWindow()"&gt;
      &lt;!-- Moves the second window twenty pixels 
           to the right --&gt;
      &lt;method name="moveWindow"&gt;
        var increment = 20;
        var originalX = this.parent.parent.windowTwo.getAttribute('x');
        var newX = originalX + increment;
        this.parent.parent.windowTwo.setAttribute('x', newX);
      &lt;/method&gt;
    &lt;/button&gt;
    <em>&lt;button text="Bigger Button" 
            onclick="this.parent.button1.moveWindow()"/&gt;</em>
  &lt;/window&gt;
&lt;/canvas&gt;
</example>


<p>Both buttons now cause the window to move. However, it's confusing that one button points to a method in another button. 
Since windowTwo is doing the moving, why not make the method part of the window, and have both buttons point to that? 
Instead of addressing it with the whole <code>this.parent&#x2026;</code> dot syntax, we can give it an <attribute>id</attribute>, and 
access it globally:</p>

<example title="Using the &lt;ID&gt; tag">
&lt;canvas width="500" height="200"&gt;
  &lt;window x="100" y="60" 
          title="Window 2" name="windowTwo" id="windowTwoId"&gt;
    &lt;!-- Moves the second window twenty pixels 
         to the right --&gt;
    <em>&lt;method name="moveWindow"&gt;
      var increment = 20;
      var originalX = this.getAttribute('x');
      var newX = originalX + increment;
      this.setAttribute('x', newX);
    &lt;/method&gt;</em>
    &lt;text&gt;This is the second window.&lt;/text&gt;
  &lt;/window&gt;
  &lt;window x="20" y="20" width="210"
      title="Simple Window"&gt;
    &lt;simplelayout axis="x" spacing="4"/&gt;
    &lt;button text="My button" name="button1" 
            onclick="<em>windowTwoId.moveWindow()</em>"/&gt;
    &lt;button text="Bigger Button" 
            onclick="<em>this.parent.parent.windowTwo.moveWindow()</em>"/&gt;
  &lt;/window&gt;
&lt;/canvas&gt;
</example>

<p>Just to illustrate <attribute>id</attribute>s and <attribute>name</attribute>s, one button is addressing the window
 relatively using its <attribute>name</attribute>, and the other globally, using its <attribute>id</attribute>. 
Note that the <attribute>id</attribute> and <attribute>name</attribute> could have been the same, they were intentionally different 
in this example.</p>


<h2>Methods and arguments</h2>

<p>In the forgoing example we have two buttons that do the same thing. Why not make them do different things? 
Move the box left and right, perhaps? We might write another method to move the box to the left, but it would be more elegant to
 use the same method for both directions. Just as with functions, we can pass arguments to methods.</p>

<p>Here's one possible solution:</p>

<example title="methods and arguments">
&lt;canvas width="500" height="200"&gt;
  &lt;window x="100" y="60" 
          title="Window 2" name="windowTwo" id="windowTwoId"&gt;
    &lt;!-- Moves the second window twenty pixels 
         in specified direction --&gt;
    &lt;method name="moveWindow" <em>args="direction"</em>&gt;
      // decide which direction to go
      <em>if (direction == "left") {
       var increment = -20;
      } else if (direction == "right") {
        var increment = 20;
      }</em>
      var originalX = this.getAttribute('x');
      var newX = originalX + increment;
      this.setAttribute('x', newX);
    &lt;/method&gt;
    &lt;text&gt;This is the second window.&lt;/text&gt;
  &lt;/window&gt;
  &lt;window x="20" y="20" width="210"
      title="Simple Window"&gt;
    &lt;simplelayout axis="x" spacing="4"/&gt;
    &lt;button text="Move Left" name="button1" 
            onclick="<em>windowTwoId.moveWindow('left')</em>"/&gt;
    &lt;button text="Move Right" 
            onclick="<em>windowTwoId.moveWindow('right')</em>"/&gt;
  &lt;/window&gt;
&lt;/canvas&gt;
</example>

<p>We can pass more than one argument to a method, just as with a function:</p>

<example title="Passing multiple arguments to a method">
&lt;canvas width="500" height="200"&gt;
  &lt;window x="100" y="60"
          title="Window 2" name="windowTwo" id="windowTwoId"&gt;
    &lt;!-- Moves the second window twenty pixels 
         in specified direction --&gt;
    &lt;method name="moveWindow" args="direction<em>, distance</em>"&gt;
      // decide which direction to go
      if (direction == "left") {
        <em>var increment = -1 * distance;</em>
      } else if (direction == "right") {
        <em>var increment = distance;</em>
      }
      var originalX = this.getAttribute('x');
      var newX = originalX + increment;
      this.setAttribute('x', newX);
    &lt;/method&gt;
    &lt;text&gt;This is the second window.&lt;/text&gt;
  &lt;/window&gt;
  &lt;window x="20" y="20" width="300"
      title="Simple Window"&gt;
      &lt;simplelayout axis="x" spacing="4"/&gt;
      &lt;button text="Left 2" name="button1" 
              onclick="windowTwoId.<em>moveWindow('left', 2)</em>"/&gt;
      &lt;button text="Left 20" name="button2" 
              onclick="windowTwoId.<em>moveWindow('left', 20)</em>"/&gt;
      &lt;button text="Right 20" 
              onclick="windowTwoId.<em>moveWindow('right', 20)</em>"/&gt;
      &lt;button text="Right 2" 
              onclick="windowTwoId.<em>moveWindow('right', 2)</em>"/&gt;
  &lt;/window&gt;
&lt;/canvas&gt;
</example>


<h2>Using attributes to reduce complexity</h2>

<p>Continuing from the same example as above, let's look at ways to reduce the number of arguments being passed. 
Here we put the functionalilty into the button itself:</p>

<example class="code" title="More on attributes">
&lt;canvas width="500" height="200"&gt;
  &lt;window x="100" y="60"
        title="Window 2" name="windowTwo" id="windowTwoId"&gt;
    &lt;!-- Moves the second window specified number of pixels 
         in specified direction --&gt;
    <em>&lt;method name="moveWindow" args="buttonObj"&gt;
      direction = buttonObj.getAttribute("direction");
      distance = parseInt(buttonObj.getAttribute("distance"));</em>
      // decide which direction to go
      if (direction == "left") {
       var increment = -1 * distance;
      } else if (direction == "right") {
        var increment = distance;
      }
      var originalX = this.getAttribute('x');
      var newX = originalX + increment;
      this.setAttribute('x', newX);
    &lt;/method&gt;
    &lt;text&gt;This is the second window.&lt;/text&gt;
  &lt;/window&gt;
  &lt;window x="20" y="20" width="300"
      title="Simple Window"&gt;
    &lt;simplelayout axis="x" spacing="4"/&gt;
    &lt;button onclick="windowTwoId.moveWindow(<em>this</em>)"&gt;Left 2
      <em>&lt;attribute name="direction" value="'left'"/&gt;
      &lt;attribute name="distance" value="'2'"/&gt;</em>
    &lt;/button&gt;
    &lt;button onclick="windowTwoId.moveWindow(<em>this</em>)"&gt;Left 20
      <em>&lt;attribute name="direction" value="'left'"/&gt;
      &lt;attribute name="distance" value="'20'"/&gt;</em>
    &lt;/button&gt;
    &lt;button onclick="windowTwoId.moveWindow(<em>this</em>)"&gt;Right 20
      <em>&lt;attribute name="direction" value="'right'"/&gt;
      &lt;attribute name="distance" value="'20'"/&gt;</em>
    &lt;/button&gt;
    &lt;button onclick="windowTwoId.moveWindow(<em>this</em>)"&gt;Right 2
      <em>&lt;attribute name="direction" value="right" type="string"/&gt;
      &lt;attribute name="distance" value="'2'"/&gt;</em>
    &lt;/button&gt;
  &lt;/window&gt;
&lt;/canvas&gt;
</example>

<p>The buttons have attributes which we have named "distance" and "direction". 
The values of those attributes need to be in <i>double quoted strings</i>, because the value needs to be a JavaScript expression, 
not a string or a number. That's the reason for the <code>value="''"</code>.
</p>
<p> Alternatively we could give the <tagname>attribute</tagname> tag an 
attribute <code>type="string"</code>, as shown in the "right 2" button. In this case
the word "right" does not need to be single-quoted.</p>

<p>This example is actually more lengthy than the previous one, but it demonstrates the power of object oriented programming in LZX```. 
If the number of attributes were to grow, and if various buttons had different attributes, the code would still remain very clear.</p>

</body>
</html>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
